package com.zhou.code.template;

import com.zhou.code.Constant;
import com.zhou.code.ColumnUtil;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TemplateUtil {

    public static String forRegex = "(?=(?=(#\\[for::start::))([\\s\\S]+?)(?<=(\\]#)))([\\s\\S]+?)(?<=(#\\[for::end\\]#))";
    public static String forContentRegex = "(?<=(?=(#\\[for::start::))([\\s\\S]+?)(?<=(\\]#)))([\\s\\S]+?)(?=(#\\[for::end\\]#))";
    public static String forParamRegex = "(?<=(#\\[for::start::))([\\s\\S]+?)(?=(\\]#))";
    public static String columnNameRegex = "(?<=(#\\[param::))(.+?)(?=((?=(::))([\\s\\S]+?)(?<=(\\]#))))";
    public static String columnRuleRegex = "(?<=((?<=(#\\[param::))(.+?)(?<=(::))))(.+?)(?=(\\]#))";
    public static String columnRegex = "(?=(#\\[param::))([\\s\\S]+?)(?<=(\\]#))";

    public static List<String> regexMatchStr(String str, String regex) {
        List<String> result = new LinkedList<>();
        Pattern pattern = Pattern.compile(regex);
        Matcher m = pattern.matcher(str);
        while (m.find()) {
            result.add(m.group());
        }
        return result;
    }

    public static Node spliteRoot(Node node) {
        String[] strs = node.content.split(forRegex);
        if (strs.length == 1) {//TODO 这里有个BUG，如果没有for，就不能进行解析
            return spliteColumn(node, NodeType.PARENT);
        }
        List<String> matchStr = regexMatchStr(node.content, forRegex);
        List<Node> child = new ArrayList<>(strs.length + matchStr.size());
        for (int i = 0 ; i < strs.length - 1 ; i ++) {
            Node strNode = new Node();
            strNode.content = strs[i];
            strNode.nodeType = NodeType.PARENT;
            spliteColumn(strNode, NodeType.PARENT);
            child.add(strNode);

            Node forNode = new Node();
            forNode.content = regexMatchStr(matchStr.get(i), forContentRegex).get(0);
            forNode.content = trimLeft(forNode.content);
            forNode.param = new Param();
            forNode.param.paramName = regexMatchStr(matchStr.get(i), forParamRegex).get(0);
            spliteColumn(forNode, NodeType.FOR);
            child.add(forNode);
        }
        Node strNode = new Node();
        strNode.content = strs[strs.length - 1];
        spliteColumn(strNode, NodeType.PARENT);//TODO 这里的nodetype不对
        child.add(strNode);
        node.child = child;
        return node;
    }

    public static Node spliteColumn(Node node, NodeType defaultType) {
        String[] strs = node.content.split(columnRegex);
        if (strs.length == 1) {
            node.child = new ArrayList<>();
            Node strNode = new Node();
            strNode.content = strs[0];
            strNode.nodeType = NodeType.STRING;
            node.child.add(strNode);
            node.nodeType = NodeType.STRING;
            return node;
        }
        node.nodeType = defaultType;
        List<String> matchStr = regexMatchStr(node.content, columnRegex);
        List<Node> child = new ArrayList<>(strs.length + matchStr.size());
        for (int i = 0 ; i < strs.length - 1 ; i ++) {
            Node strNode = new Node();
            strNode.content = strs[i];
            strNode.nodeType = NodeType.STRING;
            child.add(strNode);

            Node columnNode = new Node();
            columnNode.param = new Param();
            columnNode.param.columnRule = ColumnRule.valueOf(regexMatchStr(matchStr.get(i), columnRuleRegex).get(0));
            columnNode.param.paramName = regexMatchStr(matchStr.get(i), columnNameRegex).get(0);
            columnNode.nodeType = NodeType.ATTRIBUTE;
            child.add(columnNode);
        }
        Node strNode = new Node();
        strNode.content = strs[strs.length - 1];
        strNode.nodeType = NodeType.STRING;
        child.add(strNode);
        node.child = child;
        return node;
    }

    public static Node getTemplate(String name) throws IOException {
        try (FileReader fr = new FileReader(Constant.RESOURCE_DIR + name);
             BufferedReader bf = new BufferedReader(fr)) {
            String str;
            String fileContent = "";
            // 按行读取字符串
            while ((str = bf.readLine()) != null) {
                fileContent += (str + "\n");
            }
            Node root = new Node();
            root.content = fileContent;
            root.nodeType = NodeType.PARENT;
            return spliteRoot(root);
        }
    }

    public static String getTemplateFileName(String targetName, String fileSuffix, String fileType) {
        return Optional.of(targetName)
                .map(ColumnUtil::underlineToHump)
                .map(ColumnUtil::capitalizeFirstLetter)
                .map(name -> name + fileSuffix + "." + fileType)
                .get();
    }

    private static String trimLeft(String str) {
        char[] val = str.toCharArray();
        int len = val.length;
        int st = 0;
        while ((st < len) && (val[st] <= ' ')) {
            st++;
        }
        return st > 0 ? str.substring(st) : str;
    }

}
